using System;
using System.Collections;


namespace SharpWars.Core.AI
{
    
    class FindPath
    {
        //Metoda przyjmuje jako parametry wspolrzedne X,Y poczatku sciezki
        // oraz X,Y konca sciezki
        //Zwraca liste z obliczona droga

        public ArrayList FPath(int StartX, int StartY, int GoalX, int GoalY)
        {
            // Lista w ktorej przechowywany bedzie wynik
            ArrayList SolutionPathList = new ArrayList();

            // Ustawienie punktu koncowego NodeGoal

            Node NodeGoal = new Node(null, null, 0, GoalX, GoalY);
            
            // Ustawienie punktu startowego wyszukiwania sciezki

            Node NodeStart = new Node(null, NodeGoal, 0, StartX, StartY);

            // Tworzymy dwie listy z nodami jedna dla przechowywania 
            // drog do sprawdzenia druga do przechowywania sprawdzonych 

            SortedCostNodeList OPEN = new SortedCostNodeList();
            SortedCostNodeList CLOSED = new SortedCostNodeList();
            
            //Dodajemy do listy element startowy
            OPEN.Push(NodeStart);

            //jezeli lista OPEN posiada jakis element wykonywana jest petla 
            while (OPEN.Count > 0)
            {
                
                //pobranie z listy elementu 
                Node node_current = OPEN.Pop();

                
                //sprawdzenie czy znalezlismy rozwiazanie
                if (node_current.IsMatch(NodeGoal))
                {
                    NodeGoal.ParrentNode = node_current.ParrentNode;
                    break;
                }

                //wyszukanie mozliwych drog z bierzacego elementu
                ArrayList successors = node_current.GetSuccessors();

                
                foreach (Node node_successor in successors)
                {
                   
                    int oFound = OPEN.IndexOf(node_successor);

                    
                    if (oFound > 0)
                    {
                        Node existing_node = OPEN.NodeAt(oFound);
                        if (existing_node.CompareTo(node_current) <= 0)
                            continue;
                    }


                    
                    int cFound = CLOSED.IndexOf(node_successor);

                    
                    if (cFound > 0)
                    {
                        Node existing_node = CLOSED.NodeAt(cFound);
                        if (existing_node.CompareTo(node_current) <= 0)
                            continue;
                    }

                   
                    if (oFound != -1)
                        OPEN.RemoveAt(oFound);
                    if (cFound != -1)
                        CLOSED.RemoveAt(cFound);

                    
                    OPEN.Push(node_successor);

                }
                
                CLOSED.Push(node_current);
            }

            Node p = NodeGoal;
            
            while (p != null)
            {
                int[] coordinates = new int[2];
                coordinates[0] = p.ParrentNode.X - p.X;
                coordinates[1] = p.ParrentNode.Y - p.Y;
                SolutionPathList.Insert(0, coordinates);
                p = p.ParrentNode;
            }


            
            return SolutionPathList;
        }
    }
}
